package com.rxx.ztheme

import com.android.build.api.transform.*
import com.android.build.gradle.internal.pipeline.TransformManager
import org.apache.commons.codec.digest.DigestUtils
import org.apache.commons.io.FileUtils
import org.gradle.api.Project

/**
 * @author 冉超群
 * @date 2017/12/5-17:35
 * @desc https://www.2cto.com/kf/201604/499386.html
 */
public class ClassInjectionTransform extends Transform {

    Project project

    String androidJarPath = null

    String zthemeinjectJarPath = null

    List<String> noInjectClass = new ArrayList<>()

    ClassInjectionTransform(Project project) {
        this.project = project
    }

    @Override
    String getName() {
        return Config.TASK_NAME
    }

    @Override
    Set<QualifiedContent.ContentType> getInputTypes() {
        return TransformManager.CONTENT_CLASS
    }

    @Override
    Set<? super QualifiedContent.Scope> getScopes() {
        return TransformManager.SCOPE_FULL_PROJECT
    }

    @Override
    boolean isIncremental() {
        return false
    }

    @Override
    void transform(Context context,
                   Collection<TransformInput> inputs,
                   Collection<TransformInput> referencedInputs,
                   TransformOutputProvider outputProvider,
                   boolean isIncremental) throws IOException, TransformException, InterruptedException {

        InjectUtils tInjectUtils =new InjectUtils()
        inputs.each { TransformInput input ->
            input.jarInputs.find { JarInput jarInput ->
                tInjectUtils.appendClassPath(jarInput.file.getAbsolutePath())
            }

            input.directoryInputs.each { DirectoryInput directoryInput ->
                tInjectUtils.appendClassPath(directoryInput.file.getAbsolutePath())
            }
        }
        File injectConfigFIle = new File(project.getProjectDir().getAbsolutePath() + File.separator + Config.INJECT_RULE_FILE_NAME)
        injectConfigFIle.eachLine('utf-8') {
            String[] tStrs = it.split(" ")
            if (tStrs[0] == Config.KEY_ANDROID_JAR) {
                androidJarPath = tStrs[1]
                System.out.println("add android.jar path:" + androidJarPath)
            } else if (tStrs[0] == Config.KEY_NO_INJECT_CLASS) {
                noInjectClass.add(tStrs[1])
                System.out.println("add ignore class:" + tStrs[1])
            }
        }

        if (androidJarPath == null) {
            throw new RuntimeException("no add android.jar path")
        }

        zthemeinjectJarPath = project.getProjectDir().getAbsolutePath() +
                (Config.INJECT_JAR_PATH.replaceAll("/", File.separator))


        if (!new File(zthemeinjectJarPath).exists()) {
            throw new RuntimeException(zthemeinjectJarPath + " not exists")
        }

        tInjectUtils.appendClassPath(zthemeinjectJarPath)
        tInjectUtils.appendClassPath(androidJarPath)

        inputs.each { TransformInput input ->
            //对类型为“文件夹”的input进行遍历∂
            input.directoryInputs.each { DirectoryInput directoryInput ->
                File dest = outputProvider.getContentLocation(directoryInput.name, directoryInput.contentTypes, directoryInput.scopes, Format.DIRECTORY)
                // 将input的目录复制到output指定目录
                FileUtils.copyDirectory(directoryInput.file, dest)
                tInjectUtils.injectDir(dest.absolutePath, noInjectClass)
                project.logger.error "directoryInputs Copying ${directoryInput.file.getAbsolutePath()} to ${dest.absolutePath}"
            }
            //对类型为jar文件的input进行遍历
            input.jarInputs.each { JarInput jarInput ->
                def jarName = jarInput.name
                def md5Name = DigestUtils.md5Hex(jarInput.file.getAbsolutePath())
                if (jarName.endsWith(".jar")) {//.jar =4
                    jarName = jarName.substring(0, jarName.length() - 4)
                }
                //生成输出路径
                def dest = outputProvider.getContentLocation(jarName + md5Name,
                        jarInput.contentTypes, jarInput.scopes, Format.JAR)
                //处理jar进行字节码注入处理TODO
                FileUtils.copyFile(jarInput.file, dest)
                tInjectUtils.injectJar(dest.absolutePath)
                project.logger.error "jar Copying ${jarInput.file.absolutePath} to ${dest.absolutePath}"
            }
        }
    }
}
